import { arrayMoveMutable } from 'array-move'
import { nanoid } from 'nanoid'

export { debounce, throttle } from "throttle-debounce"

export function noop() {}

export function cloneDeep<T = any>(value: T): T {
  return JSON.parse(JSON.stringify(value))
}

export function removeItem<T = Record<string, any>>(items: T[], predicate: ArrayPredicate<T>) {
  const index = items.findIndex(predicate)
  if (~index) {
    items.splice(index, 1)
  }
}

export function sortItem<T = Record<string, any>>(items: T[], predicate: ArrayPredicate<T>, type: 'up' | 'down') {
  const index = items.findIndex(predicate)
  const isFirst = index === 0
  const isLast = index === items.length - 1
  if (type === 'up') {
    if (isFirst)
      return
    const prevIndex = index - 1
    arrayMoveMutable(items, index, prevIndex)
  }
  else if (type === 'down') {
    if (isLast)
      return
    const nextIndex = index + 1
    arrayMoveMutable(items, index, nextIndex)
  }
}

export function mapToOptions<K extends string | number, V extends string>(map: Map<K,V>): Array<IOption<K>> {
  return Array.from(map).reduce((prev, [value, label], index) => {
    prev[index] = {
      value,
      label
    }
    return prev
  }, new Array<IOption<K>>(map.size))
}

export function isSetValue(value: unknown) {
  return typeof value !== 'undefined' && value !== null
}

export function hasOwn(object: object, key: PropertyKey): boolean {
  return Object.prototype.hasOwnProperty.call(object, key)
}

export const stripHtmlTag = (html: string) => {
  // html tag
  const tagReg = /<.+?>/gim
  // \n
  const nlReg = /\n/gi
  // html entity
  const entityReg = /&.*?;/gi
  html = html.replace(tagReg, "")
  html = html.replace(nlReg, "")
  html = html.replace(entityReg, "")
  return html
}

export function buildUUID(size?: number) {
  return nanoid(size)
}

export function privatifyMobile(input: string) {
  if (!input) return input
  return input.replace(/^(\d{3})(?:\d+)(\d{2})$/, "$1******$2")
}

export function toValue<T>(value: MaybeGetter<T>): T {
  return typeof value === "function" ? value() : value
}
